import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.oned.EAN13Writer;

import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class MultiBarcodeGenerator1 {

    private static final int LEFT_GUARD_WIDTH = 3;
    private static final int CENTER_GUARD_WIDTH = 5;
    private static final int RIGHT_GUARD_WIDTH = 3;
    private static final int LEFT_DATA_WIDTH = 42;
    private static final int RIGHT_DATA_WIDTH = 42;

    // 配置参数
    private static final int BAR_WIDTH = 2;
    private static final int BAR_HEIGHT = 80;
    private static final int GUARD_EXTENSION = 10;
    private static final int FONT_SIZE = 14;
    private static final int MARGIN_X = 20;
    private static final int MARGIN_Y = 20;
    private static final int ROW_SPACING = 30;
    private static final int COLUMN_SPACING = 20;
    private static final int BARCODES_PER_ROW = 10; // 每行显示10个条码

    public static void main(String[] args) {
        String[] barcodes = {
                // 您的条码列表...
                "6926498698144", "6941217203546", "6941217207605", "6941217207612", "6941217207629",
                "6941217207636", "6941217207643", "6941217207650", "6941217207667", "6941217207674",
                "6941217207681", "6941217207704", "6941217207711", "6941217207728", "6941217207735",
                "6926498624785", "6926498624792", "6926498624808", "6926498624815", "6926498624860",
                "6926498624877", "6926498624884", "6926498624891", "6926498624747", "6926498624754",
                "6926498624761", "6926498624778", "6926498624822", "6926498624839", "6926498624846",
                "6926498624853", "6941217207780", "6941217207810", "6941217207827", "6941217207841",
                "6941217207865", "6941217207872", "6941217207797", "6941217207803", "6941217207834",
                "6941217207858", "6941217207889", "6941217207896", "6941217207902", "6941217207919",
                "6941217207926", "6941217207933", "6941217207940", "6941217207957", "6941217207964",
                "6941217207971", "6941217207988", "6941217207995", "6941217208008", "6941217208015",
                "6941217208022", "6941217208039", "6941217208046", "6941217208053", "6941217208060",
                "6941217208077", "6941217208084", "6941217208091", "6941217208107", "6941217208114",
                "6941217208121", "6941217208138", "6941217208145", "6941217208152", "6941217208169",
                "6941217208176", "6941217208183", "6941217208190", "6941217208206", "6941217208213",
                "6941217208220", "6941217208237", "6941217208244", "6941217208251", "6941217208268",
                "6941217208275", "6941217208282", "6941217208299"
        };

        String svg = generateMultiBarcodeSVG(barcodes);
        saveSVGToFile(svg, "multi_barcodes.svg");
        System.out.println("SVG文件已生成，每行显示" + BARCODES_PER_ROW + "个条码");
    }

    public static String generateMultiBarcodeSVG(String[] barcodes) {
        // 计算单个条码宽度
        int singleBarcodeWidth = calculateSingleBarcodeWidth();

        // 计算SVG总尺寸
        int rows = (int) Math.ceil((double) barcodes.length / BARCODES_PER_ROW);
        int svgWidth = MARGIN_X * 2 + (singleBarcodeWidth * BARCODES_PER_ROW)
                + (COLUMN_SPACING * (BARCODES_PER_ROW - 1));
        int svgHeight = MARGIN_Y * 2 + rows * (BAR_HEIGHT + ROW_SPACING + FONT_SIZE)
                - ROW_SPACING; // 最后一行不需要行间距

        StringBuilder svg = new StringBuilder();
        svg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        svg.append("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"")
                .append(svgWidth).append("\" height=\"").append(svgHeight).append("\">\n");
        svg.append("<rect width=\"100%\" height=\"100%\" fill=\"white\"/>\n");

        // 生成条码
        int currentX = MARGIN_X;
        int currentY = MARGIN_Y;

        for (int i = 0; i < barcodes.length; i++) {
            if (i > 0 && i % BARCODES_PER_ROW == 0) {
                // 换行
                currentX = MARGIN_X;
                currentY += BAR_HEIGHT + ROW_SPACING;
            }

            try {
                String barcodeSVG = generateSingleBarcodeSVG(barcodes[i], currentX, currentY);
                svg.append(barcodeSVG);
                currentX += singleBarcodeWidth + COLUMN_SPACING;
            } catch (Exception e) {
                System.err.println("生成条码失败: " + barcodes[i] + " - " + e.getMessage());
            }
        }

        svg.append("</svg>");
        return svg.toString();
    }

    private static int calculateSingleBarcodeWidth() {
        // EAN-13总模块数 = 左保护(3) + 左数据(42) + 中保护(5) + 右数据(42) + 右保护(3) = 95
        return 95 * BAR_WIDTH;
    }

    private static String generateSingleBarcodeSVG(String barcode, int startX, int startY)
            throws WriterException {
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.MARGIN, 0);
        BitMatrix matrix = new EAN13Writer().encode(barcode, BarcodeFormat.EAN_13,
                0, BAR_HEIGHT - GUARD_EXTENSION, hints);

        StringBuilder sb = new StringBuilder();

        // 绘制条码
        for (int x = 0; x < matrix.getWidth(); x++) {
            boolean isGuard = isGuardPosition(x);
            int height = isGuard ? BAR_HEIGHT : (BAR_HEIGHT - GUARD_EXTENSION);

            if (matrix.get(x, 0)) {
                sb.append(String.format("<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" fill=\"black\"/>\n",
                        startX + x * BAR_WIDTH, startY, BAR_WIDTH, height));
            }
        }

        // 添加数字
        addBarcodeText(sb, barcode, startX, startY + BAR_HEIGHT + FONT_SIZE - 5);
        return sb.toString();
    }

    private static void addBarcodeText(StringBuilder svg, String barcode, int startX, int textY) {
        // 首数字（起始符左侧）
        int leftGuardCenter = startX + (LEFT_GUARD_WIDTH * BAR_WIDTH) / 2;
        svg.append(String.format("<text x=\"%d\" y=\"%d\" font-family=\"Source Han Sans CN\" font-size=\"%d\" text-anchor=\"middle\">%s</text>\n",
                leftGuardCenter - (LEFT_GUARD_WIDTH * BAR_WIDTH + 10), textY, FONT_SIZE, barcode.charAt(0)));

        // 左侧6位数字
        int leftDataStart = startX + LEFT_GUARD_WIDTH * BAR_WIDTH;
        for (int i = 0; i < 6; i++) {
            int charX = leftDataStart + (i * 7 + 3) * BAR_WIDTH;
            svg.append(String.format("<text x=\"%d\" y=\"%d\" font-family=\"Source Han Sans CN\" font-size=\"%d\" text-anchor=\"middle\">%s</text>\n",
                    charX, textY, FONT_SIZE, barcode.charAt(1 + i)));
        }

        // 右侧6位数字
        int rightDataStart = leftDataStart + LEFT_DATA_WIDTH * BAR_WIDTH + CENTER_GUARD_WIDTH * BAR_WIDTH;
        for (int i = 0; i < 6; i++) {
            int charX = rightDataStart + (i * 7 + 3) * BAR_WIDTH;
            svg.append(String.format("<text x=\"%d\" y=\"%d\" font-family=\"Source Han Sans CN\" font-size=\"%d\" text-anchor=\"middle\">%s</text>\n",
                    charX, textY, FONT_SIZE, barcode.charAt(7 + i)));
        }
    }

    private static boolean isGuardPosition(int x) {
        return (x < LEFT_GUARD_WIDTH) ||
                (x >= LEFT_GUARD_WIDTH + LEFT_DATA_WIDTH &&
                        x < LEFT_GUARD_WIDTH + LEFT_DATA_WIDTH + CENTER_GUARD_WIDTH) ||
                (x >= LEFT_GUARD_WIDTH + LEFT_DATA_WIDTH + CENTER_GUARD_WIDTH + RIGHT_DATA_WIDTH);
    }

    private static void saveSVGToFile(String svg, String filename) {
        try (FileWriter writer = new FileWriter(filename)) {
            writer.write(svg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}